/*
 * Copyright 2007. Mount Sinai Hospital, Toronto, Canada.
 * 
 * Licensed under the GNU Lesser General Public License, Version 2. You
 * can find a copy of the license at:
 * 
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
 * 
 * IN NO EVENT SHALL MOUNT SINAI HOSPITAL BE LIABLE TO ANY PARTY FOR DIRECT, 
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST 
 * PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
 * EVEN IF MOUNT SINAI HOSPITAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE.
 * 
 * MOUNT SINAI HOSPITAL SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND 
 * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". 
 * MOUNT SINAI HOSPITAL HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
 */
package com.sinai.mshab.client.ui.aggregate;

import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.sinai.mshab.client.util.Util;
import com.sinai.mshab.client.ui.FormComponent;

/**
 * This class is extended by SingleConditional and MultiConditional classes.
 * Essential purpose of this widget is to contain 2 different widgets, and whow
 * the second one, depending on the value of the first widget.
 * 
 * @author serge
 * 
 */
public abstract class ConditionComponent extends AggregateFormComponent {

	/** We need to have access to our widgets */
	private FormComponent conditionWidget, showWidget;

	/** Variables to keep track of the condition */
	protected String condition[];

	protected boolean condition_met = false;

	private boolean vertical;

	/**
	 * Initialize this ConditionalComponent with the appropriate fields.
	 * 
	 * @param widget1
	 *            the first widget based on which widget2 is showed or not.
	 * @param widget2
	 *            the second widget, is not visible until the right condition is
	 *            met.
	 * @param con
	 *            the array of values widget1 could return for widget2 to
	 *            appear.
	 * @param vertical
	 *            specifies whether widget2 should go below (vertical) or to the
	 *            right (not vertical) of widget1.
	 */
	protected void initializeConditionComponent(FormComponent widget1,
			FormComponent widget2, String con[], boolean vertical) {

		// set the approriate variables.
		this.conditionWidget = widget1;
		this.showWidget = widget2;
		this.condition = con;
		this.vertical = vertical;

		// the widgets are stored vertically in a panel.
		Panel panel;
		if (vertical) {
			panel = new VerticalPanel();
		} else {
			panel = new HorizontalPanel();
		}

		panel.add(widget1);
		panel.add(widget2);

		// add my DataReceiver as my sub component's DataReciever.
		widget1.setData_receiver(getData_receiver());
		widget2.setData_receiver(getData_receiver());

		// adding this widget as widget1's observer
		widget1.addObserver(this);

		// widget 2 should not be visible at this point
		widget2.setVisible(false);

		// startring the panel.
		initWidget(panel);
	}

	/**
	 * Listen for changes in conditionWidget.
	 * @param event
	 *            the message sent to us by widget1, the current answer of
	 *            widget.
	 */
	public void receiveNotification(FormComponent who, FormComponent originator) {

		// retrieve the answer of widget 1
		String val = who.getAnswer().getFirstAnswer();

		// check if the answer appears in the condition
		boolean foundit = false;

		if (val != null) {
			for (int i = 0; i < condition.length; i++) {
				if (val.equalsIgnoreCase(condition[i])) {
					foundit = true;
					break;
				}
			}
			// check if val fits the condition
			condition_met = foundit;
			showWidget.setVisible(foundit);
		}

	}

	public boolean conditionSatisfied() {
		return condition_met;
	}

	/**
	 * Returns the first widget, i.e. the condition widget.
	 * 
	 * @return the first widget.
	 */
	public FormComponent getConditionWidget() {
		return conditionWidget;
	}

	/**
	 * Set the first widget to <code>widget1</code>.
	 * 
	 * @param widget1
	 *            the new first widget.
	 */
	public void setConditionWidget(FormComponent widget1) {
		this.conditionWidget = widget1;
	}

	/**
	 * Returns the second widget, i.e. the condition widget.
	 * 
	 * @return the second widget.
	 */
	public FormComponent getShowWidget() {
		return showWidget;
	}

	/**
	 * Set the second widget to <code>widget2</code>.
	 * 
	 * @param widget2
	 *            the new second widget.
	 */
	public void setShowWidget(FormComponent widget2) {
		this.showWidget = widget2;
	}

	public void sendAnswer(DataReceiver receiver) {
		// depending on the value of conditon, return the value of either
		// first or second widget.
		if (condition_met)
			showWidget.sendAnswer(receiver);
		else
			conditionWidget.sendAnswer(receiver);
	}

	/**
	 * Returns the condition that needs to be fulfilled in
	 * <code>contionWidget</code> for <code>showWidget</code> to appear.
	 * 
	 * @return the condition the condition that eneds to be fulfilled for
	 *         <code>showWidget</code> to appear.
	 */
	public String[] getCondition() {
		return condition;
	}

	/**
	 * The new condition that needs to be fulfilled in
	 * <code>contionWidget</code> for <code>showWidget</code> to appear.
	 * 
	 * @param condition
	 *            the condition to set
	 */
	public void setCondition(String[] condition) {
		this.condition = condition;
	}

	/**
	 * Returns whether this <code>ConditionComponent</code> is displayed
	 * vertically. If false is returned, then this
	 * <code>ConditionComponent</code> is horizontally displayed.
	 * 
	 * @return the vertical
	 */
	public boolean isVertical() {
		return vertical;
	}

	/**
	 * @see FormComponent#isEmpty()
	 */
	public boolean isEmpty() {

		boolean empty = true;

		// check emptiness of appropriate widget depending on the condition
		if (condition_met) {
			empty = showWidget.isEmpty();
		} else {
			empty = conditionWidget.isEmpty();
		}

		return empty;
	}

	public VerticalPanel toReport() {

		// we just need to get the the printable version from our two
		// components.
		VerticalPanel printableVersion = new VerticalPanel();
		FormComponent condition = getConditionWidget();
		FormComponent show = getShowWidget();

		// make sure the condition widget exists.
		if (condition != null) {
			printableVersion.add(Util.callToPrint(condition));
		}

		// make sure the show widget exists and only show it if the condition is
		// met.
		if (show != null && condition_met) {
			printableVersion.add(Util.callToPrint(getShowWidget()));
		}

		return printableVersion;
	}
}